package com.gitee.wsl.doc.prosemirror.model.mark

import com.gitee.wsl.doc.prosemirror.model.attr.AttributeSpec
import com.gitee.wsl.doc.prosemirror.model.dom.out.DOMOutputSpec
import com.gitee.wsl.doc.prosemirror.model.dom.parser.rule.ParseRule

// Used to define marks when creating a schema.
interface MarkSpec {
    // The attributes that marks of this type get.
    val attrs: Map<String, AttributeSpec>?

    // Whether this mark should be active when the cursor is positioned at its end (or at its start
    // when that is also the start of the parent node). Defaults to true.
    val inclusive: Boolean?

    // Determines which other marks this mark can coexist with. Should be a space-separated strings
    // naming other marks or groups of marks. When a mark is [added](#model.Mark.addToSet) to a set,
    // all marks that it excludes are removed in the process. If the set contains any mark that
    // excludes the new mark but is not, itself, excluded by the new mark, the mark can not be added
    // an the set. You can use the value `"_"` to indicate that the mark excludes all marks in the
    // schema.
    //
    // Defaults to only being exclusive with marks of the same type. You can set it to an empty
    // string (or any string not containing the mark's own name) to allow multiple marks of a given
    // type to coexist (as long as they have different attributes).
    val excludes: String?

    // The group or space-separated groups to which this mark belongs.
    val group: String?

    // Determines whether marks of this type can span multiple adjacent nodes when serialized to
    // DOM/HTML. Defaults to true.
    val spanning: Boolean?

    // Defines the default way marks of this type should be serialized to DOM/HTML. When the
    // resulting spec contains a hole, that is where the marked content is placed. Otherwise, it is
    // appended to the top node.
    val toDOM: ((mark: Mark, inline: Boolean) -> DOMOutputSpec)?

    // Associates DOM parser information with this mark (see the corresponding
    // [node spec field](#model.NodeSpec.parseDOM)). The `mark` field in the rules is implied.
    val parseDOM: List<ParseRule>?

    // Mark specs can include additional properties that can be
    // inspected through [`MarkType.spec`](#model.MarkType.spec) when
    // working with the mark.
    // [key: string]: any
}

data class MarkSpecImpl(
    override val attrs: Map<String, AttributeSpec>? = null,
    override val inclusive: Boolean? = null,
    override val excludes: String? = null,
    override val group: String? = null,
    override val spanning: Boolean? = null,
    override val toDOM: ((mark: Mark, inline: Boolean) -> DOMOutputSpec)? = null,
    override val parseDOM: List<ParseRule>? = null
) : MarkSpec